package com.platform.qujia.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.platform.qujia.config.BasicInfo;
import com.platform.qujia.config.RedisConfig;
import com.platform.qujia.constantEnum.DecimalConstant;
import com.platform.qujia.constantEnum.PayWayPayTypeEnum;
import com.platform.qujia.constantEnum.TianQuetechPayEnum;
import com.platform.qujia.controller.CouponController;
import com.platform.qujia.controller.ElectronicMembershipCardController;
import com.platform.qujia.dao.*;
import com.platform.qujia.enums.*;
import com.platform.qujia.param.request.*;
import com.platform.qujia.param.response.YunhuaPayRes;
import com.platform.qujia.param.response.YunhuaResponse;
import com.platform.qujia.pay.PayChannelHandler;
import com.platform.qujia.pay.PaymentStrategy;
import com.platform.qujia.pay.QueryOrderStrategy;
import com.platform.qujia.pay.strategy.YunhuaChannel;
import com.platform.qujia.pojo.*;
import com.platform.qujia.pojo.dto.*;
import com.platform.qujia.service.*;
import com.platform.qujia.utils.CodeMsg;
import com.platform.qujia.utils.MathUtil;
import com.platform.qujia.utils.ResultData;
import com.platform.qujia.utils.exception.CustomException;
import com.yunhua.oil.common.core.utils.SpringUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @date 2023/10/17
 */
@Service
public class ElectronicCardServiceImpl implements ElectronicCardService {

    private static final Logger log = LoggerFactory.getLogger(ElectronicCardServiceImpl.class);

    @Autowired
    private ElectronicMembershipCardService electronicMembershipCardService;
    @Autowired
    private CustomerCardSettingMapper customerCardSettingMapper;
    @Autowired
    private AppUserInfoService appUserInfoService;
    @Autowired
    private EnterpriseService enterpriseService;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private ElectronicMembershipCardController electronicMembershipCardController;
    @Autowired
    private CouponController couponController;
    @Value("${message.channel}")
    private String channel;
    @Autowired
    private CouponIssueMapper couponIssueMapper;
    @Autowired
    private CouponUserMapper couponUserMapper;
    @Autowired
    private CouponInfoMapper couponInfoMapper;
    @Autowired
    private ReductionActivityBalanceRecordService reductionActivityBalanceRecordService;
    @Autowired
    private CustomerCardSettingDetailService customerCardSettingDetailService;
    @Autowired
    private OrderPrintService orderPrintService;
    @Autowired
    private PayWayMapper payWayMapper;
    @Autowired
    private PayChannelHandler payChannelHandler;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private CustomerPointsRecordService customerPointsRecordService;
    @Value("${domain.payName}${server.servlet.context-path}/yunHuaCardNotice?payType=pos&pId=")
    private String yunhuaDzkNotifyUrl;
    @Value("${domain.payName}${server.servlet.context-path}/getCardRechargeCallback")
    private String sxfDzkNotifyUrl;

    @Override
    @Transactional
    public CustomerCardUseRecord posUpdateBalance(CustomerCardChangeDto cardChangeDto) {
        log.info("pos机电子卡充值,{}",cardChangeDto);
        BigDecimal amt = cardChangeDto.getAmt();
        BigDecimal presentAmt = cardChangeDto.getPresentAmt();
        if(amt == null && presentAmt == null){
            throw new CustomException(CodeMsg.PARAMS_NUll);
        }
        if (amt != null) {
            amt = amt.setScale(2,RoundingMode.DOWN);
            if (amt.compareTo(BigDecimal.ZERO)<0) {
                throw new CustomException("充值金额必须为正数");
            }
            cardChangeDto.setAmt(amt);
        }
        if(presentAmt != null){
            presentAmt = presentAmt.setScale(2,RoundingMode.DOWN);
            if(presentAmt.compareTo(BigDecimal.ZERO)<0){
                throw new CustomException("赠送金额必须为正数");
            }
            cardChangeDto.setPresentAmt(presentAmt);
        }
        amt = MathUtil.add(null,amt);
        presentAmt = MathUtil.add(null,presentAmt);
        if(amt.compareTo(BigDecimal.ZERO)<=0 && presentAmt.compareTo(BigDecimal.ZERO)<=0){
            throw new CustomException("输入金额必须为正数");
        }
        if (cardChangeDto.getAmt()==null) {
            cardChangeDto.setAmt(amt);
        }
        if (cardChangeDto.getPresentAmt()==null) {
            cardChangeDto.setPresentAmt(presentAmt);
        }
        Station station = enterpriseService.selectStationById(cardChangeDto.getStationId().intValue());
        if (station == null) {
            throw new CustomException("油站未找到");
        }

        CustomerCardSetting cardSetting = customerCardSettingMapper.getOneJoinEnterprise(CustomerCardSetting.builder()
                .enterpriseId(station.getEnterpriseId())
                .build());
        if (!StringUtils.equals("1", cardSetting.getCardEnabledFlag())) {
            throw new CustomException("油企未开启电子卡");
        }

        if(!StringUtils.contains(cardSetting.getCardOilsType(),cardChangeDto.getCardType())){
            throw new CustomException("油企未启用"+ ElectronCardType.getByKey(cardChangeDto.getCardType(),ElectronCardType.GAS).getName() +"卡");
        }

        AppUserInfo userInfo = new AppUserInfo();
        userInfo.setStationId(station.getEnterpriseId());
        userInfo.setMobilePhone(cardChangeDto.getMobilePhone());
        userInfo = appUserInfoService.getAppUserInfo(userInfo);
        if (userInfo == null) {
            throw new CustomException("会员未找到");
        }
        CustomerElectronicCard customerElectronicCardRes = electronicMembershipCardService.getAndCreateCustomerElectronicCard(userInfo,cardChangeDto.getCardType(),station);
        if (customerElectronicCardRes == null) {
            throw new CustomException("电子卡未找到");
        }
        if (customerElectronicCardRes.getId() == null) {
            throw new CustomException("创建电子卡失败");
        }
        cardChangeDto.setOperateType(0);
        cardChangeDto.setCouponIds(null);
        return updateCardBalance(customerElectronicCardRes,station,userInfo,cardChangeDto);
    }

    @Override
    @Transactional
    public void pcUpdateBalance(CustomerCardChangeDto cardChangeDto){
        if (cardChangeDto.getAmt().compareTo(BigDecimal.ZERO)==0) {
            // 调增余额为0直接返回
            return;
        }
        log.info("pc端调整余额,{}",cardChangeDto);
        cardChangeDto.setAmt(cardChangeDto.getAmt().setScale(2,RoundingMode.DOWN));
        CustomerElectronicCard card = new CustomerElectronicCard();
        card.setId(Math.toIntExact(cardChangeDto.getId()));
        CustomerElectronicCard customerElectronicCardRes = electronicMembershipCardService.getElectronicCardInfo(card);
        if (customerElectronicCardRes == null) {
            throw new CustomException("电子卡未找到");
        }
        int stationId2;
        if(Objects.nonNull(customerElectronicCardRes.getStationId2())){
            stationId2 = customerElectronicCardRes.getStationId2();
        }else {
            if(Objects.isNull(cardChangeDto.getStationId())){
                throw new CustomException(CodeMsg.STATION_NOT_EXIST);
//                return AjaxResult.error("请选择油站主体");
            }
            stationId2 = Math.toIntExact(cardChangeDto.getStationId());
        }
        Station station = enterpriseService.selectStationById(stationId2);
        if(Objects.isNull(station)){
            throw new CustomException(CodeMsg.STATION_NOT_EXIST);
        }
        AppUserInfo userInfo = new AppUserInfo();
        userInfo.setStationId(station.getEnterpriseId());
        userInfo.setMobilePhone(cardChangeDto.getMobilePhone());
        userInfo = appUserInfoService.getAppUserInfo(userInfo);
        if (userInfo == null) {
            userInfo = new AppUserInfo();
        }
        cardChangeDto.setCardType(customerElectronicCardRes.getCardOilsType());
        cardChangeDto.setPresentAmt(BigDecimal.ZERO);
        updateCardBalance(customerElectronicCardRes,station,userInfo,cardChangeDto);
    }

    @Override
    public ScanOrderDTO dzkScanRecharge(DzkPosRechargeReq req) {
        log.info("电子卡扫码充值---入参:{}",req);
        if (StringUtils.isBlank(req.getAmt())) {
            throw new CustomException("输入的余额为0");
        }
        PayWay payWayForm=new PayWay();
        payWayForm.setUseType(PayWayUseTypeEnum.RECHARGE.getValue().toString());             //使用类型
        payWayForm.setStationId(req.getStationId());
        payWayForm.setAppType(PayWayServiceChargeEnum.APPTYPE_WECHAT.getValue().toString());
        PayWay payWay = payWayMapper.getOneStationPayWay(payWayForm); //获取该油站的支付类型，默认找微信的
        if (payWay == null || payWay.getServiceCharge() == null) {
            // 找不到查找支付宝的
            payWayForm.setAppType(PayWayServiceChargeEnum.APPTYPE_ALIPAY.getValue().toString());
            payWay = payWayMapper.getOneStationPayWay(payWayForm);
        }
        if (payWay == null || payWay.getServiceCharge() == null) {
            throw new CustomException("找不到支付渠道");
        }
        RechargeBalance rechargeBalance = new RechargeBalance();
        rechargeBalance.setStationId(req.getStationId());
        rechargeBalance.setAmt(req.getAmt());
        rechargeBalance.setCardOilsType(req.getCardType());
        rechargeBalance.setMobilePhone(req.getMobilePhone());
        rechargeBalance.setOperator(req.getOilPersonnelId());
        ResultData<String> resultData = electronicMembershipCardController.rechargeBalance(rechargeBalance);
        if (resultData.getRetCode() != 0) {
            throw new CustomException(resultData.getMessage(),resultData.getRetCode());
        }
        CustomerCardUseRecord cardUseRecord = electronicMembershipCardService.selectCustomerCardUseRecordByOrderNo(resultData.getData());
        CustomerCardUseRecord updated = new CustomerCardUseRecord();
        updated.setId(cardUseRecord.getId());
        updated.setServiceCharge(cardUseRecord.getAmt().multiply(DecimalConstant.O_001).multiply(payWay.getServiceCharge()).setScale(4, RoundingMode.HALF_UP));
        updated.setPayWayId(Long.valueOf(payWay.getPayWayId()));
        electronicMembershipCardService.updateCardUseRecordRecharge(updated);
        BigDecimal presentAmt = req.getPresentAmt();
        Integer preRecordId = 0;
        if (presentAmt != null) {
            presentAmt = presentAmt.setScale(2,RoundingMode.DOWN);
            if(presentAmt.compareTo(BigDecimal.ZERO)>0){
                log.info("添加赠送金额记录,pAmt:[{}]",presentAmt);
                CustomerCardUseRecord customerCardUseRecord = new CustomerCardUseRecord();
                customerCardUseRecord.setOrderNo(cardUseRecord.getOrderNo()+'5');
                customerCardUseRecord.setCustomerNo(cardUseRecord.getCustomerNo());
                customerCardUseRecord.setCustomerName(cardUseRecord.getCustomerName());
                customerCardUseRecord.setStationId(cardUseRecord.getStationId());
                customerCardUseRecord.setEnterpriseId(cardUseRecord.getEnterpriseId());
                customerCardUseRecord.setCardOilsType(cardUseRecord.getCardOilsType());
                customerCardUseRecord.setUsageType("+");
                customerCardUseRecord.setPayType(CardRecordType.POS_PRESENT.getKey());
                customerCardUseRecord.setAmt(BigDecimal.ZERO);
                customerCardUseRecord.setPresentAmt(presentAmt);
                customerCardUseRecord.setBalance(cardUseRecord.getBalance().add(presentAmt));
                customerCardUseRecord.setCreateTime(new Date());
                customerCardUseRecord.setMobilePhone(cardUseRecord.getMobilePhone());
                customerCardUseRecord.setStatus("0");
                customerCardUseRecord.setOperator(req.getOilPersonnelId());
                electronicMembershipCardService.insetCardUseRecordConsumption(customerCardUseRecord);
                preRecordId = customerCardUseRecord.getId();
            }
        }
        PayWayPayTypeEnum payTypeEnum = PayWayPayTypeEnum.getByValue(Integer.valueOf(payWay.getPayType()));
        PaymentStrategy strategy = payChannelHandler.getPaymentStrategy(payTypeEnum);
        try{
            Object preParam = null;
            if (payTypeEnum == PayWayPayTypeEnum.Pay_Type_Accompanying_payment) {
                TradeReverseScanPayParameter param=new TradeReverseScanPayParameter();
                param.setOrgId(BasicInfo.TRADE_REVERSE_PAY_ORGID);
                param.setReqId(req.getReqId());
                param.setTimestamp(req.getTimestamp());
                param.setMno(payWay.getMno());
                param.setOrdNo(cardUseRecord.getOrderNo());
                param.setAuthCode(req.getAuthCode());
                param.setAmt(cardUseRecord.getAmt().toString());
                param.setSubject("POS机充值");
                param.setTrmIp(req.getTrmIp());
//                param.setExtend(CardRecordType.POS_RECHARGE.getKey()+","+preRecordId);
                param.setExtend(String.format("{\"payType\":\"%s\",\"pId\":%d}",CardRecordType.POS_RECHARGE.getKey(),preRecordId));
                param.setNotifyUrl(sxfDzkNotifyUrl);
                preParam = param;
            }else if (payTypeEnum == PayWayPayTypeEnum.PAY_TYPE_CLOUD_HUA){
                YunHuaPayParam yunHuaPayParam = new YunHuaPayParam();
                yunHuaPayParam.setFmno(payWay.getMno());
                yunHuaPayParam.setClientOrderNo(cardUseRecord.getOrderNo());
                yunHuaPayParam.setClientSerialNo(cardUseRecord.getOrderNo());
                yunHuaPayParam.setUserId(YunhuaChannel.DEFAULT_USER_ID);

                yunHuaPayParam.setPayMode(2);
                yunHuaPayParam.setPayChannel("poly_scan");

                yunHuaPayParam.setTxnAmt(cardUseRecord.getAmt());
                yunHuaPayParam.setTxnDesc("pos扫码充值");

                YunHuaPayPayParams payParams = new YunHuaPayPayParams();

                payParams.setNotifyUrl(yunhuaDzkNotifyUrl+preRecordId);
                payParams.setAuthCode(req.getAuthCode());
                //机构号
//                String orgCode = stationEnterpriseCopInfoService.getOrgCode(StationEnterpriseCopInfoVo.builder()
//                        .stationId(String.valueOf(cardUseRecord.getStationId()))
//                        .enterpriseId(String.valueOf(cardUseRecord.getEnterpriseId())).build());
//                if(org.apache.commons.lang3.StringUtils.isNotBlank(orgCode)){
//                    payParams.setOrgCode(orgCode);
//                }
                yunHuaPayParam.setPayParams(JSONObject.toJSONString(payParams));
                preParam = yunHuaPayParam;
            }
            log.info("pos机电子卡充值调用第三方支付，渠道：{}",payTypeEnum.getKey());
            // 进行第三方支付调用
            Object result = strategy.doPay(null,null,payWay,preParam);
            if (payTypeEnum == PayWayPayTypeEnum.PAY_TYPE_CLOUD_HUA) {
                YunhuaResponse<YunhuaPayRes> response = (YunhuaResponse<YunhuaPayRes>) result;
                if (response.getData() != null) {
                    updated = new CustomerCardUseRecord();
                    updated.setId(cardUseRecord.getId());
                    updated.setTransactionId(response.getData().getTransPayNo());
                    updated.setMerchantsNumber(response.getData().getTransInfoNo());
                    electronicMembershipCardService.updateCardUseRecordRecharge(updated);
                }
            }
            // 检查调用是否成功
            TianQuetechPayEnum payEnum = strategy.checkResult3(null, result);
            log.info("pos机电子卡充值调用第三方支付成功，渠道：{}，status:{}",payTypeEnum.getKey(),payEnum);
            ScanOrderDTO scanOrder = new ScanOrderDTO();
            scanOrder.setOrderNo(cardUseRecord.getOrderNo());
            scanOrder.setStatus(payEnum);
            if (payEnum == TianQuetechPayEnum.PAY_SUCCESS) {
                // 免密同步返回成功，随行付不会回调上送地址，需手动回调
                if (payTypeEnum == PayWayPayTypeEnum.Pay_Type_Accompanying_payment) {
                    ElectronicCardServiceImpl bean = SpringUtils.getBean(ElectronicCardServiceImpl.class);
                    bean.asyncDzkCallback((TradeReversePayInfo) result,preRecordId);
                }
            }
            return scanOrder;
        }catch (Exception e){
            log.info("调用第三方支付失败，渠道：{}，ex:{}",payTypeEnum.getKey(),e.getMessage());
            if(e instanceof CustomException){
                throw e;
            }else{
                log.error(e.getMessage(),e);
                throw new CustomException("支付失败");
            }
        }
    }

    @Override
    public CustomerCardUseRecord queryDzkScanOrder(TradeReverseScanPayParameter req) {
        log.info("电子卡扫码充值-订单查询---入参:{}",req);
        CustomerCardUseRecord cardUseRecord = electronicMembershipCardService.selectCustomerCardUseRecordByOrderNo(req.getOrdNo());
        if (cardUseRecord == null) {
            throw new CustomException(CodeMsg.PAY_FAIL);
        }
        if (StringUtils.equals("1",cardUseRecord.getStatus())) {
            if (cardUseRecord.getOperator() != null) {
                SysUser sysUser = sysUserMapper.selectByPrimaryKey(Long.valueOf(cardUseRecord.getOperator()));
                if (sysUser != null) {
                    cardUseRecord.setOperatorName(sysUser.getUserName());
                }
            }
            CustomerPointsRecord pointsRecord = new CustomerPointsRecord();
            pointsRecord.setOrderNo(cardUseRecord.getOrderNo());
            pointsRecord = customerPointsRecordService.getOne(pointsRecord);
            if (pointsRecord != null && pointsRecord.getIntegral() != null) {
                cardUseRecord.setIntegral(pointsRecord.getIntegral());
            }
            CustomerCardUseRecord preRecord = electronicMembershipCardService.selectCustomerCardUseRecordByOrderNo(cardUseRecord.getOrderNo()+"5");
            if (preRecord != null) {
                cardUseRecord.setPresentAmt(MathUtil.add(cardUseRecord.getPresentAmt(),preRecord.getPresentAmt()));
                cardUseRecord.setBalance(preRecord.getBalance());
            }
            return cardUseRecord;
        }
        if(!StringUtils.equals("0",cardUseRecord.getStatus())){
            throw new CustomException(CodeMsg.PAY_FAIL);
        }
        Long payWayId = cardUseRecord.getPayWayId();
        PayWay payWay = payWayMapper.selectPayWayById(payWayId);
        if (payWay == null) {
            throw new CustomException("找不到支付渠道");
        }

        PayWayPayTypeEnum typeEnum = PayWayPayTypeEnum.getByValue(Integer.valueOf(payWay.getPayType()));

        QueryOrderStrategy strategy = payChannelHandler.getQueryOrderStrategy(typeEnum);
        log.info("查询支付状态，{}",typeEnum.getKey());
        TradePaymentRecordsDO record = new TradePaymentRecordsDO();
        record.setOrderSn(cardUseRecord.getOrderNo());
        TianQuetechPayEnum orderStatus = strategy.getOrderStatus(req,record,payWay);
        log.info("查询支付状态结束，{}",typeEnum.getKey());
        if(orderStatus == TianQuetechPayEnum.PAY_SUCCESS || orderStatus == TianQuetechPayEnum.PAY_PAYING){
            throw new CustomException(typeEnum.getKey()+"-支付中",CodeMsg.TRADE_REVERSE_PAY_WAIT_MINUTE.getRetCode());
        }

        if(orderStatus == TianQuetechPayEnum.PAY_FAIL){
            CustomerCardUseRecord updated = new CustomerCardUseRecord();
            updated.setId(cardUseRecord.getId());
            updated.setStatus("2");
            electronicMembershipCardService.updateCardUseRecordRecharge(updated);
            throw new CustomException(typeEnum.getKey()+"-支付失败");
        }
        return null;
    }

    @Async
    public void asyncDzkCallback(TradeReversePayInfo payInfo,Integer preId){
        electronicMembershipCardService.sxfDzkRechargeCallback(payInfo.getPayTime(),payInfo.getOrdNo(),payInfo.getOriTranAmt(),payInfo.getTransactionId(),payInfo.getPayType(),CardRecordType.POS_RECHARGE.getKey(),preId);
    }

    /**
     * 电子卡充值
     * @param card
     * @param station
     * @param userInfo
     * @param cardChangeDto amt和presentAmt必须有一个大于0
     * @return
     */
    private CustomerCardUseRecord updateCardBalance(CustomerElectronicCard card,Station station,AppUserInfo userInfo,CustomerCardChangeDto cardChangeDto){
        BigDecimal amt = cardChangeDto.getAmt();
        BigDecimal presentAmt = cardChangeDto.getPresentAmt();
        CustomerCardUseRecord useRecord = null;
        if (amt.compareTo(BigDecimal.ZERO)>0) {
            useRecord = addRechargeAmt(card, station, userInfo, cardChangeDto);
        }
        CustomerCardUseRecord presentRecord = null;
        if (presentAmt.compareTo(BigDecimal.ZERO)>0) {
            presentRecord = manualAddPresentAmt(card, useRecord, station, userInfo, cardChangeDto);
        }
        if (useRecord != null && presentRecord != null) {
            useRecord.setPresentAmt(MathUtil.add(useRecord.getPresentAmt(),presentRecord.getPresentAmt()));
            useRecord.setBalance(presentRecord.getBalance());
        }else if(useRecord == null && presentRecord != null){
            useRecord = presentRecord;
        }
        //打印小票
        if(0 == cardChangeDto.getOperateType()){
            orderPrintService.printUpateEletronicCard(useRecord);
        }
        return useRecord;
    }

    /**
     * 增加本金账户，计算充值活动
     * @param card
     * @param station
     * @param userInfo
     * @param cardChangeDto
     * @return
     */
    private CustomerCardUseRecord addRechargeAmt(CustomerElectronicCard card,Station station,AppUserInfo userInfo,CustomerCardChangeDto cardChangeDto){
        Integer operateType = cardChangeDto.getOperateType();
        BigDecimal operateAmt = cardChangeDto.getAmt();
        List<CustomerCardSetting> cardRechargeSettingList = electronicMembershipCardService.getCardRechargeMinAmt(
                CustomerCardSetting.builder()
                        .stationId(station.getEnterpriseId())  //油企ID
                        .build());
        CalPresentAmt calPresentAmt = new CalPresentAmt();
        calPresentAmt.setPresentAmt(BigDecimal.ZERO);
        if (operateType==0) {
            log.info("pos机充值计算赠送金额");
            RechargeBalance rechargeBalance = new RechargeBalance();
            rechargeBalance.setStationId(station.getStationId());
            rechargeBalance.setEnterpriseId(station.getEnterpriseId());
            calPresentAmt = electronicMembershipCardController.calPresentAmt(cardRechargeSettingList, card.getCardOilsType(), operateAmt, rechargeBalance,"xj",false);
            log.info("ccsdId:{},总共赠送：{}",calPresentAmt.getCcsdId(),calPresentAmt.getPresentAmt());
        }

        CustomerCardUseRecord customerCardUseRecord = new CustomerCardUseRecord();
        customerCardUseRecord.setOrderNo(com.platform.qujia.utils.StringUtils.generateOrdNo());
        customerCardUseRecord.setCustomerNo(userInfo.getMemberCode());
        customerCardUseRecord.setCustomerName(userInfo.getBlogNickName());
        customerCardUseRecord.setStationId(station.getStationId());
        customerCardUseRecord.setEnterpriseId(station.getEnterpriseId());
        customerCardUseRecord.setCardOilsType(cardChangeDto.getCardType());
        customerCardUseRecord.setCcsdId(calPresentAmt.getCcsdId());

        //BigDecimal beforeBalance = card.getTotalAmt();
        BigDecimal afterBalance;
        ElectronicCardSubRes res;
        String usageType;
        String payType;
        if (operateType == 1){
//            if (beforeBalance.compareTo(operateAmt) < 0 ){
//                throw new CustomException("余额不够扣减");
////                return AjaxResult.error("余额不够扣减");
//            }
            res = card.subtractAmount(operateAmt);
            if (!res.isSuccess()) {
                throw new CustomException("余额不够扣减");
            }
            afterBalance = card.getTotalAmt();
            usageType = "-";
            payType = CardRecordType.MANUAL_SUB.getKey();
        }else {
            card.setAmt(MathUtil.add(card.getAmt(),operateAmt));
            card.setPresentAmt(MathUtil.add(card.getPresentAmt(),calPresentAmt.getPresentAmt()));
            afterBalance = card.getTotalAmt();
            res = ElectronicCardSubRes.newInstance();
            res.setAmt(operateAmt);
            res.setPresentAmt(calPresentAmt.getPresentAmt());
            res.setSuccess(true);
            usageType = "+";
            payType = CardRecordType.MANUAL_ADD.getKey();

            //增加赠送金额记录
            if(calPresentAmt.getPresentAmt().compareTo(BigDecimal.ZERO)>0){
                //充值赠额记录
                customerCardSettingDetailService.createRecord(calPresentAmt.getPresentAmt(),PresentAmountRecord.businessName_customerCardUseRecord,userInfo.getMobilePhone(),customerCardUseRecord.getOrderNo(),
                        PresentAmountRecord.purpose_add,card.getId().longValue(),calPresentAmt.getCcsdId());
            }
        }

        customerCardUseRecord.setUsageType(usageType);
        customerCardUseRecord.setPayType(payType);
        customerCardUseRecord.setAmt(res.getAmt());
        customerCardUseRecord.setPresentAmt(res.getPresentAmt());
        customerCardUseRecord.setBalance(afterBalance);
        customerCardUseRecord.setCreateTime(new Date());
        customerCardUseRecord.setMobilePhone(userInfo.getMobilePhone());
        customerCardUseRecord.setStatus("1");
        customerCardUseRecord.setReason(cardChangeDto.getReason());
        customerCardUseRecord.setOperator(cardChangeDto.getOperator());
        electronicMembershipCardService.insetCardUseRecordConsumption(customerCardUseRecord);

        Integral integral = new Integral();
        if (StringUtils.equals(CardRecordType.MANUAL_ADD.getKey(), customerCardUseRecord.getPayType())) {
            integral = electronicMembershipCardService.rechargeActivityGiveIntegral(customerCardUseRecord);
            customerCardUseRecord.setIntegral(integral.getPresentIntegral());
        }
        CustomerElectronicCard updatedCard = new CustomerElectronicCard();
        updatedCard.setId(card.getId());
        updatedCard.setRecentlyTime(new Date());
        if (operateType==0) {
            electronicMembershipCardService.incrCustomerElectronicCardBalance(res.getAmt(),res.getPresentAmt(),updatedCard);
        }else{
            electronicMembershipCardService.incrCustomerElectronicCardBalance(res.getAmt().negate(),res.getPresentAmt().negate(),updatedCard);
        }




        if (operateType==0) {
            log.info("充值参与立减优惠");
            reductionActivityBalanceRecordService.createBalanceRecord(null,card.getCardOilsType(),operateAmt,
                    station, Long.valueOf(userInfo.getUserId()),
                    userInfo.getMobilePhone(),station.getEnterprise(),"xj");
            log.info("pos机充值后发优惠卷");
            couponController.sendCounponByCardUserRecord(customerCardUseRecord);
        }

        if(StringUtils.equals("1",cardRechargeSettingList.get(0).getManualChangeWxNotifyFlag()) && StringUtils.isNotBlank(userInfo.getBlogOpenid())){
            // 余额调整消息推送
            BalanceChangeWxNotifyDTO notifyDTO = new BalanceChangeWxNotifyDTO();
            notifyDTO.setEnterpriseId(customerCardUseRecord.getEnterpriseId());
            notifyDTO.setOpenId(userInfo.getBlogOpenid());
            notifyDTO.setCustomerNo(userInfo.getMemberCode());
            if (operateType==1) {
                notifyDTO.setAmt(customerCardUseRecord.getAmt().negate());
            }else{
                notifyDTO.setAmt(customerCardUseRecord.getAmt());
            }
            notifyDTO.setPresentAmt(customerCardUseRecord.getPresentAmt());
            notifyDTO.setBalance(customerCardUseRecord.getBalance());
            notifyDTO.setPresentIntegral(integral.getPresentIntegral());
            notifyDTO.setTotalIntegral(integral.getTotalIntegral());
            notifyDTO.setStationName(station.getStationName());

            UniversalRedisMessageDto messageDto = new UniversalRedisMessageDto();
            messageDto.setData(JSONObject.toJSONString(notifyDTO));
            messageDto.setMessageType(WxConsumptionMessageEnum.BALANCE_CHANGE_PUSH.getValue());
            messageDto.setTitle("调整余额 推送公众号信息");
            redisTemplate.convertAndSend(RedisConfig.TOPIC_Template_message_push_1,JSONObject.toJSONString(messageDto));
        }

        // 发券
        if (CollectionUtils.isNotEmpty(cardChangeDto.getCouponIds())) {

            log.info("优惠券发放ids：{}", cardChangeDto.getCouponIds());
            //调用发券接口
            DrawCoupon drawCoupon = new DrawCoupon();
            drawCoupon.setCouponIssueIdList(cardChangeDto.getCouponIds());
            drawCoupon.setMobilePhoneList(Collections.singletonList(card.getMobilePhone()));
            drawCoupon.setEnterpriseId(Long.valueOf(station.getEnterpriseId()));
            ResultData data = sendCoupon(drawCoupon);
            int retCode = data.getRetCode();
            String message = data.getMessage();
            if (retCode != 0) {
                log.info("调整余额手动发优惠劵失败，code:[{}],msg:[{}]",retCode,message);
                return customerCardUseRecord;
            }
            log.info("调整余额手动发优惠劵成功，code:[{}],msg:[{}]",retCode,message);
            //todo 推送消息
            Integer messagePush = cardChangeDto.getMessagePush();
            if (messagePush == 1) {
                //todo 创建发送消息对象
                AdjustmentBalancePush balancePush = new AdjustmentBalancePush();
                balancePush.setCouponIds(cardChangeDto.getCouponIds());
                balancePush.setUserPhone(card.getMobilePhone());
                balancePush.setStationId(Long.valueOf(station.getStationId()));
                balancePush.setEnterpriseId(Long.valueOf(station.getEnterpriseId()));


                UniversalRedisMessageDto dto=new UniversalRedisMessageDto();
                dto.setData(JSONObject.toJSONString(balancePush));
                dto.setMessageType(WxConsumptionMessageEnum.PERSONAL_COUPON_ISSUANCE_PUSH.getValue());
                dto.setTitle("调整余额发送优惠券 推送公众号信息");
                String str=JSONObject.toJSONString(dto);
                redisTemplate.convertAndSend(channel, str);
            }
        }
        log.info("customerCardUseRecord=====【{}】", customerCardUseRecord);
        return customerCardUseRecord;
    }

    /**
     * 仅增加赠送账户，不计算充值活动
     * @param card
     * @param useRecord
     * @param station
     * @param userInfo
     * @param cardChangeDto
     * @return
     */
    private CustomerCardUseRecord manualAddPresentAmt(CustomerElectronicCard card,CustomerCardUseRecord useRecord,Station station,AppUserInfo userInfo,CustomerCardChangeDto cardChangeDto){
        BigDecimal presentAmt = cardChangeDto.getPresentAmt();
        BigDecimal balance;
        if (useRecord == null) {
            balance = card.getTotalAmt().add(presentAmt);
        }else{
            balance = useRecord.getBalance().add(presentAmt);
        }
        Date now = new Date();
        CustomerCardUseRecord customerCardUseRecord = new CustomerCardUseRecord();
        customerCardUseRecord.setOrderNo(com.platform.qujia.utils.StringUtils.generateOrdNo());
        customerCardUseRecord.setCustomerNo(userInfo.getMemberCode());
        customerCardUseRecord.setCustomerName(userInfo.getBlogNickName());
        customerCardUseRecord.setStationId(station.getStationId());
        customerCardUseRecord.setEnterpriseId(station.getEnterpriseId());
        customerCardUseRecord.setCardOilsType(cardChangeDto.getCardType());
        customerCardUseRecord.setUsageType("+");
        customerCardUseRecord.setPayType(CardRecordType.POS_PRESENT.getKey());
        customerCardUseRecord.setAmt(BigDecimal.ZERO);
        customerCardUseRecord.setPresentAmt(presentAmt);
        customerCardUseRecord.setBalance(balance);
        customerCardUseRecord.setCreateTime(now);
        customerCardUseRecord.setMobilePhone(userInfo.getMobilePhone());
        customerCardUseRecord.setStatus("1");
        customerCardUseRecord.setReason(cardChangeDto.getReason());
        customerCardUseRecord.setOperator(cardChangeDto.getOperator());
        electronicMembershipCardService.insetCardUseRecordConsumption(customerCardUseRecord);
        CustomerElectronicCard updatedCard = new CustomerElectronicCard();
        updatedCard.setId(card.getId());
        updatedCard.setRecentlyTime(now);
        electronicMembershipCardService.incrCustomerElectronicCardBalance(null, presentAmt,updatedCard);
        return customerCardUseRecord;
    }

    public ResultData sendCoupon(DrawCoupon drawCoupon) {
        ResultData a;
        drawCoupon.setRandomFlag(System.currentTimeMillis() + RandomStringUtils.randomNumeric(7));
        List<String> couponIssueIdList = drawCoupon.getCouponIssueIdList();
        List<String> mobilePhoneList = drawCoupon.getMobilePhoneList();
        if (couponIssueIdList != null && !couponIssueIdList.isEmpty() && mobilePhoneList != null && !mobilePhoneList.isEmpty()) {

            //校验
            for (String couponIssueId : couponIssueIdList) {
                for (String mobilePhone : mobilePhoneList) {
                    Map<String, String> paramMap = new HashMap<>();
                    paramMap.put("mobilePhone", mobilePhone);
                    paramMap.put("couponIssueId", couponIssueId);
                    CouponIssue souponIssue = couponIssueMapper.selectCouponIssueById(couponIssueId);
                    int userIssueGiveCount = couponUserMapper.selectUserIssueGiveCount(paramMap);
                    CouponUserGiveCount cugc = couponUserMapper.selectCouponUserGiveCount(CouponUserGiveCount.builder().mobilePhone(mobilePhone).couponIssueId(couponIssueId).randomFlag(drawCoupon.getRandomFlag()).build());
                    Integer couponinfoId = couponIssueMapper.getCouponInfoIdByIssueId(Long.parseLong(couponIssueId));
                    CouponInfo couponInfo = couponInfoMapper.selectCouponInfoById(couponinfoId);
                    if (couponInfo != null && couponInfo.getGetCouponNum() >= couponInfo.getCouponNum()) {
                        return ResultData.error("优惠券手动发放失败优惠券"+couponInfo.getCouponRemark()+"已不能再领");
                    }
                    if (souponIssue != null && userIssueGiveCount >= souponIssue.getGiveCount()) {
                        return ResultData.error("优惠券手动发放失败用户已不能再领");
                    }
                    if (souponIssue != null && userIssueGiveCount >= souponIssue.getGiveCount()) {
                        return ResultData.error("优惠券手动发放失败用户已不能再领");
                    }
                    if (souponIssue == null || !souponIssue.getStatus().equals("1")) {
                        return ResultData.error("优惠券状态不对");
                    }
                    if (cugc != null && cugc.getIssueGiveCount() + 1 >= souponIssue.getGiveLimit()) {
                        return ResultData.error("优惠券剩余数量不足");
                    } else if (1 >= souponIssue.getGiveLimit()) {
                        return ResultData.error("优惠券剩余数量不足");
                    }


                }

            }
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            使用
            int counter = 1; // 初始化计数器
            List<CouponUser> saveCouUserList = new ArrayList<>();
            List<Integer> updateTemIdsCountList = new ArrayList<>();
            for (String couponIssueId : couponIssueIdList) {
                for (String mobilePhone : mobilePhoneList) {
                    Integer couponinfoId = couponIssueMapper.getCouponInfoIdByIssueId(Long.parseLong(couponIssueId));
                    drawCoupon.setCouponIssueId(couponIssueId);

                    drawCoupon.setCouTemIds(couponinfoId.toString());
                    // 生成后三位的字符串，保证至少有三位，不足的在前面补0
                    String counterString = String.format("%03d", counter);

                    // 获取原始的 randomFlag，即去掉后三位的部分
                    String originalRandomFlag = drawCoupon.getRandomFlag().substring(0, drawCoupon.getRandomFlag().length() - 3);

                    // 构建新的 randomFlag，将原始部分与后三位替换为循环数
                    String newRandomFlag = originalRandomFlag + counterString;

                    // 更新 drawCoupon 的 randomFlag
                    drawCoupon.setRandomFlag(newRandomFlag);

                    // 增加计数器
                    counter++;
//                    CouponIssue couponIssue = couponIssueMapper.selectCouponIssueById(couponinfoId.toString());
                    CouponInfo couponInfo = couponInfoMapper.selectCouponInfoById(couponinfoId);
                    Date startTime = new Date();     //开始时间
                    Date endTime = new Date();       //结束时间

                    switch (couponInfo.getEffectiveTimeType()) {
                        case "1":   //固定时间
                            //startTime = couponTemplate.getEffectiveTimeStart();
                            endTime = couponInfo.getEffectiveTimeEnd();
                            break;
                        case "2":   //领取后有效天数
                            startTime = new Date();
                            Calendar instance = Calendar.getInstance();
                            instance.setTime(new Date());
                            instance.add(Calendar.DATE, couponInfo.getEffectiveDayNum());
                            endTime = instance.getTime();
                            break;
                    }
                    saveCouUserList.add(CouponUser.builder()
                            .mobilePhone(mobilePhone)
                            .issueId(couponIssueId)
                            .couponId(couponinfoId)
                            .couponIsUsed("0")
                            .couponNo(useMD5(drawCoupon.getEnterpriseId() + Long.toString(System.currentTimeMillis()) + Math.round((Math.random() + 1) * 1000)))
                            .enterpriseId(Math.toIntExact(drawCoupon.getEnterpriseId()))
                            .ccsdId(drawCoupon.getCcsdId() == null ? null : Long.valueOf(drawCoupon.getCcsdId()))
                            .couponGetTime(startTime)
                            .activityType(4)
                            .activityName("-")
                            .randomFlag(drawCoupon.getRandomFlag())
                            .couponEffectiveTime(formatter.format(endTime))
                            .build());
                    updateTemIdsCountList.add(couponinfoId);

                    CouponUserGiveCount cugc = couponUserMapper.selectCouponUserGiveCount(CouponUserGiveCount.builder().mobilePhone(mobilePhone).couponIssueId(couponIssueId).randomFlag(drawCoupon.getRandomFlag()).build());
                    if (null != cugc) {
                        couponUserMapper.updateCouponUserGiveCount(CouponUserGiveCount.builder()
                                .randomFlag(drawCoupon.getRandomFlag())
                                .issueGiveCount(1 + cugc.getIssueGiveCount())
                                .mobilePhone(mobilePhone)
                                .couponIssueId(couponIssueId)
                                .build());
                    } else {
                        couponUserMapper.insertCouponUserGiveCount(CouponUserGiveCount.builder()
                                .randomFlag(drawCoupon.getRandomFlag())
                                .issueGiveCount(1)
                                .mobilePhone(mobilePhone)
                                .couponIssueId(couponIssueId)
                                .build());
                    }
                }
            }

            if (null != saveCouUserList && saveCouUserList.size() > 0) {
                int i = couponUserMapper.saveBatchCouponUser(saveCouUserList);
                log.info("批量保存的用户优惠券数量：" + i);
                CouponDeduction couponDeduction = new CouponDeduction();
                couponDeduction.setUpdateTemIdsCountList(updateTemIdsCountList);
                couponDeduction.setPhoneSize(mobilePhoneList.size());
                int y = couponUserMapper.updateBatchCouponTemplate(couponDeduction);
                log.info("批量更新的优惠券模板减少的模板优惠券数量：" + mobilePhoneList.size());
                a = ResultData.success("发放成功");
            } else {
                return ResultData.error("没有可以保存的优惠券");
            }


        } else {
            a = ResultData.error("缺少用户手机号或可用的优惠券");
        }
        return a;
    }

    public static String useMD5(String passWord) {
        try {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.update(passWord.getBytes());
            return getHashString(digest);

        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            log.info(e.getMessage(),e);
        }
        return null;

    }

    private static String getHashString(MessageDigest digest) {
        StringBuilder builder = new StringBuilder();
        for (byte b : digest.digest()) {
            builder.append(Integer.toHexString((b >> 4) & 0xf));
            builder.append(Integer.toHexString(b & 0xf));
        }
        return builder.toString().toLowerCase();
    }

}
